<?php

declare(strict_types=1);

namespace app\admin\service;

use app\admin\model\Customer as CustomerModel;
use app\admin\model\Images;
use app\admin\validate\Customer as CustomerValidate;
use app\admin\service\CustomerLog as CustomerLogService;
use app\admin\service\SystemSMChannel as SystemSMChannelService;
use app\admin\common\ServiceResponse;
use app\common\service\CompleteNotificationService;
use app\admin\model\FollowRecords as ModelFollowRecords;
use PhpParser\Node\Expr\Isset_;
use think\facade\Log;
use think\facade\Db;
use app\common\RedisClient;

class Customer
{
    use ServiceResponse;

    protected $return;
    protected $logger;
    protected $validate;
    protected $model;
    public function __construct()
    {
        $this->validate = new CustomerValidate();
        $this->logger = new CustomerLogService();
        $this->model = new CustomerModel();
        $this->return = [
            'code' => 500001,
            'data' => [],
            'message' => ''
        ];
    }

    /**
     * @describe 获取客户列表
     * @author: Bobo
     * @date: 2024-06-05 18:02:26
     * @param [] type
     * @return Renderable
     */
    public function getList(int $page = 1, int $limit = 10, array $where = [], $field = "*", $attr = 0,$owner = 0, $operator_id = 0)
    {
        $return = $this->return;
        if(!isSuperAdmin($operator_id) && $owner && $owner != $operator_id ){
            $return['code'] = 0;
            $return['data'] = [];
            return  $return;
        }
        if (0 >= $page || 100 < $limit) {
            $return['code'] = 100002;
            return $return;
        }
        try {
            $query = CustomerModel::where($where);

            if (!isSuperAdmin($operator_id)) { // 非超级管理员
                switch ($attr) {
                    case 0:
                        $query->whereRaw("owner = {$operator_id} OR FIND_IN_SET('{$operator_id}', partner)");
                        break;
                    case 1:
                        $query->whereRaw("owner = {$operator_id} OR FIND_IN_SET('{$operator_id}', partner)");
                        break;
                    case 2:
                        $query->where('owner', 0);
                        break;
                    default:
                        # code...
                        break;
                }
            } else { // 超级管理员
                if (2 == $attr) {
                    $query->where('owner', 0);
                } else {
                    if($owner){
                        $query->where('owner', $owner);
                    }else{
                        $query->where('owner', '!=', 0);
                    }
                }
            }




            $total = $query->count();

            if ($total <= 0) {
                $return['code'] = 0;
            } else {
                $list = $query
                    ->field($field)
                    ->page($page, $limit)
                    ->order('id desc')
                    ->select()
                    ->toArray();

                $countryArr = array_filter(array_unique(array_column($list, 'country_id')), function ($value) {
                    return $value !== null;
                });

                $ownerArr =  array_filter(array_unique(array_column($list, 'owner')), function ($value) {
                    return $value !== null;
                });
                $countryList = Db::name('region_country')->whereIn('id', $countryArr)->column('id,cname', 'id');
                $ownerList = Db::name('operator')->whereIn('id', $ownerArr)->column('id,cname', 'id');
                foreach ($list as &$item) {

                    if (!empty($item['partner'])) {
                        $item['partner'] = array_map(function ($item) {
                            return (int) $item;
                        }, explode(',', $item['partner']));
                    } else {
                        $item['partner'] = [];
                    }

                    $item['owner_id'] = $item['owner'];
                    $item['country'] = $countryList[$item['country_id']]['cname'] ?? '';
                    $item['owner'] = $ownerList[$item['owner']]['cname'] ?? '';
                }

                $return['code'] = 0;
                $return['data'] = ['list' => $list, 'total' => $total];
            }
        } catch (\Throwable $th) {
            $return['message'] = 'Failed to retrieve list. ' . $th->getMessage();
            $return['code'] = 500001;
        }
        return $return;
    }

    /**
     * @describe 获取客户列表  折扣专用
     * @author: Bobo
     * @date: 2024-06-05 18:02:26
     * @param [] type
     * @return Renderable
     */
    public function getListFotDiscount(int $page = 1, int $limit = 10, array $where = [])
    {
        $return = $this->return;
        $field = 'id,cusname,phone,email,nickname';
        if (0 >= $page || 100 < $limit) {
            $return['code'] = 100002;
            return $return;
        }
        try {
            $query = CustomerModel::where($where);
            $total = $query->count();

            if ($total <= 0) {
                $return['code'] = 0;
            } else {
                $list = $query
                    ->field($field)
                    ->page($page, $limit)
                    ->order('id desc')
                    ->select()
                    ->toArray();

                $return['code'] = 0;
                $return['data'] = ['list' => $list, 'total' => $total];
            }
        } catch (\Throwable $th) {
            $return['message'] = 'Failed to retrieve list. ' . $th->getMessage();
            $return['code'] = 500001;
        }
        return $return;
    }

    /**
     * 获取客户详情
     * @param int $id 客户ID
     */
    public function getOneById(int $id, string $field = '*', int $operator_id = 0)
    {
        $return = $this->return;
        if (empty($id) || !is_numeric($id)) return $return;
        $data = $this->model
            ->field($field)
            ->find($id)
            ->toArray();
        $data['country'] = Db::name('region_country')->where('id', $data['country_id'])->value('cname');

        // if ($data['creator']) $data['creator'] = Db::name('operator')->where('id', $data['creator'])->value('nickname');
        // if ($data['updater'])  $data['updater'] = Db::name('operator')->where('id', $data['updater'])->value('nickname');


        if ($data['partner']) {
            $data['partner'] =    array_map('intval', explode(',', $data['partner']));
            $data['partner_value'] =  implode(" ", Db::name('operator')->whereIn('id', $data['partner'])->column('nickname'));
        }

        if (0 == $data['status']) {
            $data['status'] = "";
        }
        if (0 == $data['stage']) {
            $data['stage'] = "";
        }
        if (0 == $data['owner']) {
            $data['owner'] = "";
        }
        if (0 == $data['partner']) {
            $data['partner'] = "";
        }


        // 扩展客户信息
        $expandCustomer = Db::name('expand_customer')->where(['customer_id' => $id])->find();

        // 先检查 $expandCustomer 是否为空
        if (!empty($expandCustomer) && isset($expandCustomer['items'])) {
            $data['items'] = json_decode($expandCustomer['items'], true);

            // facebook显示用户链接
            if ($data['tripartite_channel_id']) {
                $systemSmChannel = Db::name('system_sm_channel')->field('name')->find($expandCustomer['source']);

                if ('FACEBOOK' === $systemSmChannel['name']) {

                    if ($operator_id == 0 || $operator_id !== $data['owner'] && !isSuperAdmin($operator_id)) {
                        $data['tripartite_account_value'] = '******';
                    } else {
                        $env = env('APP_ENV', 'prod');
                        $domian = config()['domain'][$env]['facebook'];
                        $data['tripartite_account_value'] = $domian . 'profile.php?id=' . $data['tripartite_account'];
                    }

                    if ($data['city'] === null) {
                        $data['city'] = $expandCustomer['city'];
                    }
                }
            }
        } else {
            $data['items'] = [];
        }


        $data['logger'] = $this->logger->getCustomerLog($id);
        $imagesModel = new Images();

        if ($data['att_path']) {
            $data['att_path'] =    array_map('intval', explode(',', $data['att_path']));
        }
        $data['att_path_urls'] = $imagesModel->getImagesByIds($data['att_path']);
        return [
            'code' => 0,
            'data' => $data
        ];
    }


    /**
     * 创建客户
     * @param array $data 创建客户的数据
     */
    public function create($data)
    {
        try {
            if (!$this->validate->scene('create')->check($data)) {
                return ['code' => 100001, 'message' => $this->validate->getError()];
            }
            $exists = CustomerModel::where('is_del', 0)
                ->where(function ($query) use ($data) {
                    if (!empty($data['email'])) {
                        $query->where('email', $data['email']);
                    }
                    if (!empty($data['phone'])) {
                        $query->where('phone', $data['phone']);
                    }
                })->find();
            if ($exists) {
                return ['code' => 200001, 'message' => '请检查手机号或邮箱'];
            }
            $res = CustomerModel::create($data);
            if ($res) {
                if (isset($data['follow_info']) && $data['follow_info']['follow_method'] && $data['follow_info']['follow_time'] && $data['follow_info']['follow_content']) {
                    $data['follow_info']['customer_id'] = $res->id;
                    $data['follow_info']['create_time'] = date('Y-m-d H:i:s', time());
                    $data['follow_info']['creator'] = $data['creator'];
                    ModelFollowRecords::create($data['follow_info']);

                    $res->last_followtime = date('Y-m-d H:i:s', time());
                    $res->save();
                }
                $this->logger->logging('创建客户', $res['id'], '手动创建');
                return ['code' => 0];
            } else {
                return ['code' => 500001];
            }
        } catch (\Throwable $th) {
            return ['code' => 500001, 'message' => '服务器内部错误：' . $th->getMessage()];
        }
    }

    /**
     * 更新客户
     * @param int $id 客户ID
     * @param array $data 更新客户的数据
     */
    public function update($data)
    {
        $res = CustomerModel::where('id', $data['id'])->find();

        if (!$res) {
            return false;
        }
        $originalCustomer = clone $res;  // 使用 clone 创建对象副本


        if ($res->owner != $data['owner']) {
            $data['allocate_time'] = date('Y-m-d H:i:s', time());
        } else {
            unset($data['allocate_time']);
        }

        foreach ($data as $key => $value) {
            if ($res->$key != $value) {
                $res->$key = $value;
            }
        }

        $exists = CustomerModel::where('is_del', 0)->where('id', '<>', $res->id)
            ->where(function ($query) use ($res) {
                if (!empty($res->email)) {
                    $query->where('email', $res->email);
                }
                if (!empty($res->phone)) {
                    $query->where('phone', $res->phone);
                }
            })->find();

        if ($exists) {
            return ['code' => 200001, 'message' => '客户已存在，请检查手机号或邮箱是否重复'];
        }

        // 处理客户变更通知
        $notifications = [];
        $ownerArr = [$res->owner, $originalCustomer->owner];
        $partnerArrNew = $res->partner ? explode(',', $res->partner) : [];
        $partnerArrOld = $originalCustomer->partner ? explode(',', $originalCustomer->partner) : [];
        $recipients = array_filter(array_unique(array_merge($ownerArr, $partnerArrNew, $partnerArrOld)));

        // 负责人变更通知
        if ($res->owner != $originalCustomer->owner) {
            if ($originalCustomer->owner == 0) {
                // 添加负责人
                $notifications[] = ['event' => 'customer_allocated', 'recipients' => $recipients, 'log' => '客户添加负责人通知发送失败'];
            } else {
                // 变更负责人 - 通知新负责人和原负责人
                $notifications[] = ['event' => 'customer_allocated', 'recipients' => $recipients, 'log' => '客户变更负责人通知发送失败'];
                $notifications[] = ['event' => 'customer_owner_transfer', 'recipients' => $recipients, 'log' => '客户转移通知发送失败'];
            }
        }

        // 合作伙伴变更通知
        if ($res->partner != $originalCustomer->partner) {
            $notifications[] = ['event' => 'customer_partner_transfer', 'recipients' => $recipients, 'log' => '客户合作伙伴变更通知发送失败'];
        }

        // 统一发送所有通知
        if (!empty($notifications)) {
            $notificationService = new CompleteNotificationService();
            foreach ($notifications as $notification) {
                try {
                    $notificationService->send($notification['event'], $res->toArray(), $notification['recipients']);
                } catch (\Exception $e) {
                    Log::error($notification['log'] . ': ' . $e->getMessage() . ' 客户ID: ' . $res->id . ' | 文件：' . $e->getFile() . ' | 行号：' . $e->getLine());
                }
            }
        }

        $result = $res->save();

        if ($result) {
            return ['code' => 0, 'message' => '操作成功'];
        } else {
            return ['code' => 1, 'message' => '操作失败'];
        }
    }

    /**
     * 删除客户
     * @param int $id 客户ID
     */
    public function delete($id)
    {
        return CustomerModel::where('id', $id)->delete();
    }

    /**
     * @describe 批量逻辑删除客户
     * @author: Bobo
     * @date: 2024-06-26 14:53:00
     * @param [arr] @required $ids 客户ID数组
     * @return Renderable
     */
    public function batchLogicalDelete($ids)
    {
        CustomerModel::startTrans();
        try {
            CustomerModel::where('id', 'in', $ids)->update(['is_del' => time()]);
            $operations = [];
            $idsArr = explode(',', $ids);
            foreach ($idsArr as $id) {
                $operations[] = [
                    'operate' => '删除',
                    'c_id' => $id,
                    'msg' => '被删除',
                ];
            }
            $this->logger->batchLogging($operations);
            CustomerModel::commit();
            $return['code'] = 0;
        } catch (\Throwable $th) {
            CustomerModel::rollback();
            $return['code'] = 500001;
            $return['message'] = $th->getMessage();
        }
        return $return;
    }

    /**
     * @describe 批量修改客户
     * @author: Bobo
     * @date: 2024-07-06 14:53:00
     * @param [arr] @required $condition 条件
     * @param [arr] @required $update 数据
     * @return Renderable
     */
    public function batchUpdate(array $condition, array $update)
    {
        $return = [
            'code' => 500001,
            'message' => 'success'
        ];
        if (empty($condition) || empty($update)) {
            $return['message'] = 'Condition and update arguments must not be empty.';
        } else {
            try {
                CustomerModel::where($condition)->update($update);
                $return['code'] = 0;
            } catch (\Throwable $th) {
                $return['message'] = 'Batch update failed. ' . $th->getMessage();
            }
        }
        return $return;
    }

    /**
     * @describe
     * @author: Bobo
     * @date: 2024-08-01 15:46:45
     * @param [int] @$operatorType 操作类型
     *   3:捞取 4:分配 5:退回
     * @param [arr] @required $condition 条件
     * @param [arr] @required $update 数据
     * @param [int] @required $customerID 客户ID
     * @return Renderable
     */
    public function operatorCustomer(int $operatorType, array $condition, array $update, int $customerID)
    {
        $return = $this->return;
        if (empty($operatorType) || empty($condition) || empty($update)) {
            $return['code'] = 100001;
            return $return;
        }
        $originalCustomer = CustomerModel::where('id', $customerID)->find();

        CustomerModel::startTrans();
        try {
            CustomerModel::where($condition)->update($update);
            $operator = '';
            $msg = '';
            $event = '';
            $recipients = [];
            switch ($operatorType) {
                case 3:
                    $operator = '捞取';
                    $msg = '从公海池被捞取';
                    break;
                case 4:
                    $operator = '分配';
                    $event = 'customer_allocated';
                    $recipients = [$update['owner']];
                    $ownerName = CustomerModel::table('db_operator')->where('id', $update['owner'])->value('cname');
                    $msg = '从公海池被分配给' . $ownerName;
                    break;
                case 5:
                    $operator = '退回';
                    $msg = '被退回公海池';
                    $event = 'customer_returned';
                    $partnerArr = $originalCustomer['partner'] ? explode(',', $originalCustomer['partner']) : [];
                    $recipients = array_merge([$originalCustomer['owner']], $partnerArr);
                    break;

                default:
                    break;
            }
            $this->logger->logging($operator, $customerID, $msg);

            CustomerModel::commit();
            if ($event) {
                // 通知
                try {
                    $notificationService = new CompleteNotificationService();
                    $customer = Db::name('customer')->where('id', $customerID)->find();
                    $notificationService->send($event, $customer, $recipients);
                } catch (\Exception $e) {
                    Log::error('客户分配通知发送失败: ' . $e->getMessage() . ' 客户ID: ' . $customerID . ' | 文件：' . $e->getFile() . ' | 行号：' . $e->getLine());
                }
            }


            $return['code'] = 0;
        } catch (\Throwable $th) {
            CustomerModel::rollback();
            $return['code'] = 500001;
            $return['message'] = $th->getMessage();
        }
        return $return;
    }
    /**
     * @describe
     * @author: Bobo
     * @date: 2024-07-23 10:34:00
     * @param [type] @required
     * @return Renderable
     */
    public function getFieldEnum($field)
    {
        $model = new CustomerModel();

        $res = $model->getFieldEnum($field);
        $tripartiteChannelService = new SystemSMChannelService();
        $res['tripartite_channel'] = $tripartiteChannelService->getSelectData()['data'];
        return [
            'code' => 0,
            'data' => $res
        ];
    }

    public function getSelect($where, $field = "id AS value, cusname as label", $operator_id = 0)
    {
        $where['is_del'] = 0;

        if (isset($where['cusname']) && $where['cusname']) {
            $cusname = $where['cusname'];
            unset($where['cusname']);
        } else {
            $cusname = null;
        }
        $oCategoryModel = CustomerModel::where($where);

        if (!isSuperAdmin($operator_id)) {
            $oCategoryModel->whereRaw("owner = {$operator_id} OR FIND_IN_SET('{$operator_id}', partner)");
        }

        // 如果 cusname 有值，则加上模糊查询条件
        if ($cusname) {
            $oCategoryModel->where(function ($query) use ($cusname) {
                // 在查询中添加条件：cusname 或 email 包含 cusname
                $query->where('cusname', 'like', '%' . $cusname . '%')
                    ->whereOr('email', 'like', '%' . $cusname . '%'); // 使用 whereOr 来实现 orWhere
            });
        }
        $result = $oCategoryModel->field($field)->order('id desc')->select();

        $res = $result->toArray();
        return [
            'code' => 0,
            'data' => $res
        ];
    }

    /**
     * @describe
     * @author: Bobo 获取客户操作日志
     * @date: 2025-02-10 15:09:50
     * @param [type] @required
     * @return Renderable
     */

    public function getOperationLogList(int $page = 1, int $limit = 10, array $where = [], $field = "*")
    {
        $return = $this->return;

        if (0 >= $page || 100 < $limit) {
            $return['code'] = 100002;
            return $return;
        }
        try {
            $query = $this->model->name('customer_log')->where($where);
            $total = $query->count();

            if ($total <= 0) {
                $return['code'] = 0;
            } else {
                $list = $query
                    ->field($field)
                    ->page($page, $limit)
                    ->order('id desc')
                    ->select()
                    ->toArray();

                $groupedData = [];

                // 遍历查询结果
                foreach ($list as $item) {
                    // 获取 create_time 字段的日期部分
                    $date = date('Y-m-d', strtotime($item['create_time']));

                    // 如果该日期的分组不存在，则初始化一个空数组
                    if (!isset($groupedData[$date])) {
                        $groupedData[$date] = [];
                    }

                    // 将当前记录添加到对应的日期分组中
                    $groupedData[$date][] = $item;
                }

                // 转换为期望的格式
                $newFormat = [];
                foreach ($groupedData as $date => $data) {
                    $newFormat[] = [
                        "date" => $date,
                        "data" => $data
                    ];
                }

                // 将分组后的数据赋值给 $return 数组

                $return['code'] = 0;
                $return['data'] = ['list' => $newFormat, 'total' => $total];
            }
        } catch (\Throwable $th) {
            $return['message'] = 'Failed to retrieve list. ' . $th->getMessage();
            $return['code'] = 500001;
        }
        return $return;
    }

    /**
     * @describe
     * @author: Bobo
     * @date: 2025-03-03 15:09:51 
     * @param [type] @required
     * @return Renderable
     */
    public function getApprovalRecords(int $page = 1, int $limit = 10, array $condition = [], $field = "*")
    {

        if (0 >= $page || 100 < $limit) {
            return $this->error(100002);
        }
        try {

            if (isset($condition['id']) && !empty($condition['id'])) {
                $orderId = $this->model->name('order')->where('order_category', 'order')->where('is_del', 0)->where('user_id', $condition['id'])->column('id');
                $wholesalOrderId = $this->model->name('order')->where('order_category', 'wholesal')->where('is_del', 0)->where('user_id', $condition['id'])->column('id');
                $entityId  = array_merge($orderId, $wholesalOrderId);
            }
            $where[] = ['business_module', 'like', '%order%'];
            $where[] = ['operate', 'like', '%审核%'];
            $where[] = ['entity_id', 'in', $entityId];
            $query = $this->model->name('business_log')->where($where);
            $total = $query->count();

            if ($total <= 0) {
                return $this->success();
            } else {
                $list = $query
                    ->field($field)
                    ->page($page, $limit)
                    ->order('id desc')
                    // ->group('customer_id')
                    ->select()
                    ->toArray();
                $orderRecordsIds = $wholesalOrderRecordsIds = [];

                foreach ($list as $key => $value) {
                    if ('order' == $value['business_module']) {
                        array_push($orderRecordsIds, $value['entity_id']);
                    }
                    if ('wholesal_order' == $value['business_module']) {
                        array_push($wholesalOrderRecordsIds, $value['entity_id']);
                    }
                }

                // 查询普通订单审核记录
                $orderApprovalQuery = $this->model
                    ->name('business_log')
                    ->alias('a')
                    ->join('order b', 'a.entity_id = b.id')
                    ->where([
                        ['a.business_module', 'like', '%order%'],
                        ['a.operate', 'like', '%审核%'],
                        ['a.entity_id', 'in', $orderRecordsIds]
                    ])
                    ->field('a.id,a.user_id,a.operate, a.content,a.create_time,a.business_module as order_type, a.entity_id,b.order_no,b.order_category');

                // 查询经销商订单审核记录
                $wholesalApprovalQuery = $this->model
                    ->name('business_log')
                    ->alias('a')
                    ->join('order b', 'a.entity_id = b.id')
                    ->where([
                        ['a.business_module', 'like', '%order%'],
                        ['a.operate', 'like', '%审核%'],
                        ['a.entity_id', 'in', $wholesalOrderRecordsIds]
                    ])
                    ->field('a.id,a.user_id,a.operate, a.content,a.create_time,a.business_module as order_type, a.entity_id,b.order_no,b.order_category');

                // 合并查询
                $approvalRecords = $this->model
                    ->table("({$orderApprovalQuery->buildSql()}) as sub1")
                    ->union("({$wholesalApprovalQuery->buildSql()})", true)
                    ->page($page, $limit)
                    ->order('id desc')
                    ->select()
                    ->toArray();

                $userIds = array_column($approvalRecords, 'user_id');
                $userInfo = $this->model->name('operator')->whereIn('id', $userIds)->field('id,cname')->select()->toArray();
                $userInfo = array_column($userInfo, null, 'id');

                foreach ($approvalRecords as &$item) {
                    $item['user_name'] = $userInfo[$item['user_id']]['cname'] ?? '';
                    $item['order_type'] = 'order' == $item['order_category'] ? '普通订单' : '经销商订单';
                    $item['order_id'] = $item['entity_id'];

                    unset($item['user_id'], $item['entity_id']);
                }
                return $this->success(['list' => $approvalRecords, 'total' => $total]);
            }
        } catch (\Throwable $th) {
            return $this->error(500001, 'Failed to retrieve list. ' . $th->getMessage());
        }
    }

    public function role($params)
    {
        $res = CustomerModel::where('id', $params['id'])->find();

        if (!$res) {
            return false;
        }

        if ($res['role'] == $params['role']) {
            return $this->success();
        }

        $res->role = $params['role'];
        $redis = new RedisClient();
        $redisClient = $redis->getClient();

        $token = $redisClient->get('customer_token:' . $res->id);
        if ($token) {
            $redisClient->del('customer_token:' . $res->id);
            $redisClient->select(14);
            $redisClient->del($token);
        }

        $res->save();
        $this->logger->logging('修改用户角色', $res['id'], '修改用户角色为' . ($params['role'] == 'distributor' ? '经销商' : '普通用户'));
        return $this->success();
    }
}
